'use strict';

const { Controller } = require('egg');
const fs = require('fs')
const path = require('path')
const OSS = require('ali-oss')

class HomeController extends Controller {
	// 上传图片方法
	async uploadAvator() {
		const { ctx } = this;
		// 获取上传的文件
		const file = ctx.request.files[0];
		// 获取保存文件的路径
		const publicPath = path.resolve(__dirname, '../public')
		// 复制临时文件 放入 public 目录下
		await fs.promises.copyFile(file.filepath, path.join(publicPath, file.filename))
		// 清除临时文件
		ctx.cleanupRequestFiles();
		// 返回信息
		ctx.body = {
			code: 200,
			data: {
				url: `http://localhost:7001/public/` + file.filename
			}
		};
	}

	// 文件检查接口
	async checkFile() {
		const { ctx } = this;
		// 获取请求数据     其实就是req.body
		const { hash } = ctx.request.body
		// 获取上传目录
		const publicDir = path.resolve(__dirname, '../public');
		// 获取上传目录的子目录
		const publicChildDir = (await fs.promises.readdir(publicDir)).map(v => {
			return path.join(publicDir, v)
		})
		// 查找是否存在一个文件或者文件夹和hash值是一样
		const item = publicChildDir.find(pathname => {
			const obj = path.parse(pathname);
			return obj.name === hash
		})

		if (item) {
			// 存在
			const stat = fs.statSync(item);

			if (stat.isFile()) {
				// 是文件
				ctx.body = {
					code: 201,
					message: '文件秒传成功'
				}
			} else {
				// 是文件夹
				ctx.body = {
					code: 202,
					message: '文件继续上传',
					// 读取子目录 已经上传好的切片
					data: await fs.promises.readdir(item)
				}
			}

		} else {
			// 不存在
			ctx.body = {
				code: 200,
				message: '文件未上传'
			}
		}


		// 分为三种情况
		// 1. 已经上传过      该文件存在
		// 2. 已经上传过部分  存在文件夹 
		// 3. 未上传         文件和文件夹都没有

	}

	// 文件上传接口
	async upload() {
		const { ctx } = this;
		// 获取文件
		const file = ctx.request.files[0];
		// 获取存储路径
		const filepath = file.filepath
		// 获取切片名字
		const filename = file.filename
		// 获取hash
		const hash = filename.slice(0, filename.indexOf('-'));
		// 获取上传目录
		const publicDir = path.resolve(__dirname, '../public');
		// 目标文件夹
		const targetDir = path.join(publicDir, hash);
		// 判断目录文件夹是否存在
		if (!fs.existsSync(targetDir)) await fs.promises.mkdir(targetDir)
		// 目标文件
		const targetFile = path.join(targetDir, filename)
		// 复制文件
		await fs.promises.copyFile(filepath, targetFile);
		// 删除临时文件
		ctx.cleanupRequestFiles();
		ctx.body = {
			code: 200,
			message: '文件上传Ok'
		}
	}

	// 文件合并接口
	async mergeFile() {
		const { ctx } = this;
		const { hash, extName } = ctx.request.body;
		// 获取上传目录
		const publicDir = path.resolve(__dirname, '../public');
		// 目标文件夹
		const targetDir = path.join(publicDir, hash);
		if (fs.existsSync(targetDir)) {
			// 文件夹存在
			const targetDirChild = (await fs.promises.readdir(targetDir)).sort((a, b) => {
				const a_ = a.split('-')[1]
				const b_ = b.split('-')[1]
				return a_.slice(0, a_.lastIndexOf('.')) - b_.slice(0, b_.lastIndexOf('.'))
			}).map(v => {
				console.log(v);
				return path.join(targetDir, v)
			})
			const filename = path.join(publicDir, hash + extName)

			// 开始合并
			await this.streamMergeFile(targetDirChild, filename, hash)

			ctx.body = {
				code: 200,
				message: '文件合并成功'
			}

		} else {
			ctx.body = {
				code: 404,
				message: '和并的文件不存在'
			}
		}
	}


	// 多文件合并
	async streamMergeFile(sourceFiles, targetFile, hash) {
		// 创建写入流
		const write = fs.createWriteStream(targetFile);
		// 开始递归写入文件
		return await this.readFileAndWrireFile(sourceFiles, write, hash)
	}
	// 流文件处理
	readFileAndWrireFile(sourceFiles = [], write, hash) {
		// 获取上传目录
		const publicDir = path.resolve(__dirname, '../public');

		return new Promise(async (resolve) => {
			if (sourceFiles.length === 0) {
				// 所有切片写入完毕
				// 删除临时文件件
				await fs.promises.rmdir(path.join(publicDir, hash))
				// 结束
				write.end('结束');
				resolve()
				return
			}
			// 获取源文件文件
			const source = sourceFiles.shift();
			// 创建读取流
			const read = fs.createReadStream(source);
			// 管道流写入
			read.pipe(write, { end: false });
			// 自定义 写入完成
			read.on('end', async () => {
				// 删除源文件
				await fs.promises.unlink(source)
				// 继续写入下一个切片
				this.readFileAndWrireFile(sourceFiles, write, hash);
				resolve()
			})
		})

	}

	// 上传oss 接口
	async uploadOss() {
		const { ctx } = this;

		const file = ctx.request.files[0];

		const { filepath, filename } = file

		console.log(filepath)

		// 获取云实例
		const client = new OSS({
			// yourregion填写Bucket所在地域。以华东1（杭州）为例，Region填写为oss-cn-hangzhou。
			region: 'oss-cn-shanghai',
			// 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
			accessKeyId: 'LTAI5tHBrGWJiNzpoqi6CtqV',
			accessKeySecret: 'YJBODeNsHQ75la4dzGeRvXgm3sppI3',
			// 填写Bucket名称。
			bucket: 'xixi-1',
		})

		// 上传阿里云
		const data = await client.put(filename, path.normalize(filepath))

		// 删除临时文件
		ctx.cleanupRequestFiles();

		ctx.body = {
			code: 200,
			message: '上传成功',
			data
		}
	}

	// oss 列表
	async uploadOssList() {
		const { ctx } = this
		// 获取云实例
		const client = new OSS({
			// yourregion填写Bucket所在地域。以华东1（杭州）为例，Region填写为oss-cn-hangzhou。
			region: 'oss-cn-shanghai',
			// 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
			accessKeyId: 'LTAI5tHBrGWJiNzpoqi6CtqV',
			accessKeySecret: 'YJBODeNsHQ75la4dzGeRvXgm3sppI3',
			// 填写Bucket名称。
			bucket: 'xixi-1',
		})

		const data = await client.list()

		ctx.body = {
			code: 200,
			message: '数据获取成功',
			data
		}
	}

	// 删除
	async uploadOssDelete() {
		const { ctx } = this;
		const { name } = ctx.request.body;

		// 获取云实例
		const client = new OSS({
			// yourregion填写Bucket所在地域。以华东1（杭州）为例，Region填写为oss-cn-hangzhou。
			region: 'oss-cn-shanghai',
			// 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
			accessKeyId: 'LTAI5tHBrGWJiNzpoqi6CtqV',
			accessKeySecret: 'YJBODeNsHQ75la4dzGeRvXgm3sppI3',
			// 填写Bucket名称。
			bucket: 'xixi-1',
		})

		client.useBucket("xixi-1");

		const data = await client.delete(name);

		ctx.body = {
			code: 200,
			messasge: '数据删除成功',
			data
		}
	}
}


module.exports = HomeController;
